package com.bruce.storage.service;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.bruce.storage.config.StorageConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@ConditionalOnProperty(name = "storage.type", havingValue = "oss")
public class OSSStorageService implements StorageService{

    private final OSS ossClient;

    public OSSStorageService(StorageConfig properties) {
        this.ossClient = new OSSClientBuilder().build(properties.getEndpoint(), properties.getAccessKey(), properties.getSecretKey());
    }

    @Override
    public void uploadFile(String bucketName, String contentId, String fileName, String referenceIds, MultipartFile file) {
        try {
            uploadFile(bucketName, contentId, fileName, referenceIds, file.getInputStream());
        } catch (IOException e) {
            log.error("Failed to upload file to OSS", e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public void uploadFile(String bucketName, String contentId, String fileName, String referenceIds, InputStream inputStream) {
        try {
            // 创建ObjectMetadata实例。
            ObjectMetadata metadata = new ObjectMetadata();
            String encodedString = Base64.getEncoder().encodeToString(fileName.getBytes(StandardCharsets.UTF_8));
            // 设置用户元数据。
            metadata.addUserMetadata("name", encodedString);
            if(StringUtils.isNotEmpty(referenceIds)) {
                metadata.addUserMetadata("reference_ids", referenceIds);
            }
            PutObjectResult putObjectResult = ossClient.putObject(bucketName, contentId, inputStream, metadata);
            log.info("upload file result: {}", putObjectResult.getETag());
        } catch (Exception e) {
            throw new RuntimeException("Failed to upload file to OSS", e);
        }
    }

    @Override
    public InputStream downloadFile(String bucketName, String contentId) {
        OSSObject ossObject = ossClient.getObject(bucketName, contentId);
        return ossObject.getObjectContent();
    }

    @Override
    public void deleteFile(String bucketName, String fileName) {
        VoidResult voidResult = ossClient.deleteObject(bucketName, fileName);
        log.info("delete file result: {}", voidResult.getResponse().toString());
    }

    @Override
    public void deleteFiles(String bucketName, List<String> fileNames) {
        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(fileNames));
        log.info("delete files result: {}", deleteObjectsResult.getDeletedObjects());
    }

    @Override
    public Map<String, String> getMetadata(String bucketName, String contentId) {
        // 获取对象的元数据。
        Map<String, String> userMetadata = ossClient.getObjectMetadata(bucketName, contentId).getUserMetadata();
        userMetadata.forEach((k, v) -> {
            String decodedString = new String(Base64.getDecoder().decode(v), StandardCharsets.UTF_8);
            userMetadata.put(k, decodedString);
        });
        return userMetadata;

    }
}
